package com.wry.spring.controller;

import cn.hutool.core.util.StrUtil;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.TimeZone;

/**
 * <h1>时间工具类</h1>
 *
 * @author <a href="mailto::muffliato1998@outlook.com">吴泽渠</a>
 * @since 2022/4/26
 */
public class TimeUtil {
    private static final ZoneId ZONE_ID = ZoneOffset.systemDefault();

    /**
     * 8 小时的秒数
     */
    private static final int OFFSET = 8 * 60 * 60;

    /**
     * LocalDateTime的类型匹配
     */
    private static final String LOCAL_DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
    
    /**
     * LocalDateTime -> 秒
     *
     * @param localDateTime localDateTime
     * @return 秒
     */
    public static long toSeconds(LocalDateTime localDateTime) {
        return localDateTime.atZone(ZONE_ID).toEpochSecond();
    }

    /**
     * LocalDateTime -> 毫秒
     *  竟然加了8小时
     *
     * @param localDateTime localDateTime
     * @return 毫秒
     */
    public static long toMilliSecond(LocalDateTime localDateTime) {
        // 比标准实际慢8小时，就是当前的时间了
        return localDateTime.toInstant(ZoneOffset.ofTotalSeconds(OFFSET)).toEpochMilli();
    }
    
    /**
     *  用于授权时间为Long类型转换成localdateTime
     *
     * @param time 时间戳
     * @return 过期时间
     */
    public static LocalDateTime toOauth2LocalDateTime(Long time){
        long unixTimestampInMillis = time * 1000L;
        Date date = new Date(unixTimestampInMillis);
        SimpleDateFormat sdf = new SimpleDateFormat(LOCAL_DATETIME_PATTERN);
        sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
        String formattedDate = sdf.format(date);
        return TimeUtil.toLocalDateTime(formattedDate);
    }

    /**
     * 秒级时间戳 -> LocalDateTime
     *
     * @param time 秒级时间戳
     * @return LocalDateTime
     */
    public static LocalDateTime toLocalDateTime(Long time) {
        if (time == null || time <= 0L){
            return null;
        }
        return LocalDateTime.parse(
                new SimpleDateFormat(LOCAL_DATETIME_PATTERN).format(new Date(time)),
                DateTimeFormatter.ofPattern(LOCAL_DATETIME_PATTERN)
        );
    }

    /**
     * 秒级时间戳 -> LocalDateTime
     *
     * @param timestamp 秒级时间戳
     * @return LocalDateTime
     */
    public static LocalDateTime timestampToLocalDateTime(Long timestamp) {
        if (timestamp == null || timestamp <= 0L){
            return null;
        }
        // 使用系统默认时区
        return LocalDateTime.ofInstant(Instant.ofEpochSecond(timestamp), ZoneId.systemDefault());
    }

    /**
     * 秒级时间戳 -> LocalDateTime
     *
     * @param timestamp 秒级时间戳
     * @return LocalDateTime
     */
    public static String toStrLocalDateTime(Long timestamp) {
        if (timestamp == null || timestamp <= 0L){
            return null;
        }
        // 使用系统默认时区
        Instant instant = Instant.ofEpochSecond(timestamp);
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(LOCAL_DATETIME_PATTERN);
        return localDateTime.format(formatter);
    }

    /**
     * 获取当日起始时间0时0分0秒
     *
     * @param currentTime 当前时间
     * @return 当日起始时间0时0分0秒
     */
    public static LocalDateTime getStartTimeByDate(LocalDateTime currentTime) {
        return LocalDateTime.of(
                currentTime.getYear(), currentTime.getMonth(), currentTime.getDayOfMonth(),
                0, 0, 0);
    }

    /**
     *  时间日期转换 Date -> LocalDateTime
     *
     * @param date 传入的DATE
     * @return LocalDateTime
     */
    public static LocalDateTime toLocalDateTime(Date date){
        if (date == null){
            return null;
        }
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        return instant.atZone(zoneId).toLocalDateTime();
    }

    /**
     *  时间日期转换 Date -> LocalDateTime
     * @param date string类型的 date
     * @return LocalDateTime
     */
    public static LocalDateTime  toLocalDateTime(String date){
        if (StrUtil.isBlank(date)) {
            return null;
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        return LocalDateTime.parse(date, formatter);
    }

    /**
     * 日期字符串转String->LocalDate
     * @param date
     * @return  LocalDate
     */
    public static LocalDate toLocalDate(String date){
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        return LocalDate.parse(date, formatter);
    }

    /**
     * 日期字符串转String->LocalDate
     * @param date
     * @return  LocalDate
     */
    public static String toStringDate(LocalDate date){
        final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        return dateTimeFormatter.format(date);
    }

    /**
     * 日期格式字符串
     *
     * @param date
     * @return
     */
    public static String toStrDate(LocalDate date){
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        return date.format(formatter);
    }

    /**
     *  时间日期转换 LocalDateTime -> String
     * @param date LocalDateTime
     * @return string类型的LocalDateTime
     */
    public static String toStrLocalDateTime(LocalDateTime date){
        return date == null ? "" : DateTimeFormatter.ofPattern(LOCAL_DATETIME_PATTERN).format(date);
    }
    
    /**
     *  时间转换: 获取当前时间的年月日
     * @param date 当前时间
     * @return 年月日
     */
    public static String convertDayByLocalDateTime(LocalDateTime date){
        final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        return dateTimeFormatter.format(date);
    }
    
    /**
     *  时间转换: 获取当前时间的年月日
     * @param date 当前时间
     * @return 年月日前一天
     */
    public static String convertDayMinusByLocalDateTime(LocalDateTime date){
        final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        return dateTimeFormatter.format(date.minusDays(1));
    }
    
    /**
     *  时间转换: 获取当前半小时时间戳,如输入15:43,输出则为:15:30
     * @param dateTime 当前时间
     * @return 整点时间戳
     */
    public static String getCurrentHalfTime(LocalDateTime dateTime){
        int minute = dateTime.getMinute();
        int startMinute = (minute / 30) * 30;
        LocalDateTime startDateTime = dateTime.truncatedTo(ChronoUnit.HOURS).plusMinutes(startMinute);
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm");
        return startDateTime.format(timeFormatter);
    }
    
    
    /**
     *  时间转换: 获取当前时间的整点时间戳 加一个小时
     * @param date 当前时间
     * @return 整点时间戳 加一个小时
     */
    public static String convertTimePlusHoursByLocalDateTime(LocalDateTime date){
        final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("HH:mm");
        return dateTimeFormatter.format(date.plusHours(1).withMinute(0).withSecond(0).withNano(0));
    }

    /**
     *  时间转换: 获取当前时间的整点时间戳 加半小时
     * @param dateTime 当前时间
     * @return 整点时间戳 加半小时
     */
    public static String pushHalfHour(LocalDateTime dateTime){
        int minute = dateTime.getMinute();
        int startMinute = (minute / 30) * 30;
        LocalDateTime startDateTime = dateTime.truncatedTo(ChronoUnit.HOURS).plusMinutes(startMinute);
        LocalDateTime endDateTime = startDateTime.plusMinutes(30);
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm");
        return endDateTime.format(timeFormatter);
    }

    /**
     *  时间转换: 昨日18:00
     * @param date 当前时间
     * @return 昨天18:00
     */
    public static String convertTimePlusHoursByBeforeLocalDateTime(LocalDateTime date){
        final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("HH:mm");
        return dateTimeFormatter.format(date.withHour(18).withMinute(0).withSecond(0).withNano(0));
    }

    /**
     *  时间转换: 获取当前时间的年月日
     * @param date 当前时间
     * @return 年月日后一天
     */
    public static String convertDayPlusByLocalDateTime(LocalDateTime date){
        final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        return dateTimeFormatter.format(date.plusHours(1));
    }

    /**
     * LocalDateTime -> Date
     *
     * @param dateTime LocalDateTime
     * @return Date
     */
    public static Date toDate(LocalDateTime dateTime){
        if (dateTime == null){
            return  null;
        }
        return Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * datetime-string -> 毫秒级时间戳
     *
     * @param dateTime dateTime
     * @return 时间戳
     */
    public static Long toMilliSecond(String dateTime){
        if (StrUtil.isBlank(dateTime)){
            return null;
        }
        try {
            return new SimpleDateFormat(LOCAL_DATETIME_PATTERN).parse(dateTime).getTime();
        } catch (ParseException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
    
    /**
     *  店铺授权时间提前20分钟转换 loacaldateTime -> long
     *
     * @param localDateTime 时间
     * @return 转换后的秒
     */
    public static Long toSecondCache(LocalDateTime localDateTime){
        LocalDateTime dateTime = localDateTime.minusMinutes(20);
        return toSeconds(dateTime);
    }
    
    
    /**
     *  获取到的秒级戳 减去 当前时间等于 时间差
     * @param time 授权后的时间戳
     * @return 时间戳(毫秒)
     */
    public static Long timeDifference(Long time){
        long currentTimestampMillis = System.currentTimeMillis();
        return time - currentTimestampMillis;
    }

    /**
     * 计算时间差值小时
     */
    public static BigDecimal calculateTiming(LocalDateTime subtraction, LocalDateTime subtracted) {
        final BigDecimal oneHours = new BigDecimal(3600L);
        final long second = subtraction.toInstant(ZoneOffset.UTC).getEpochSecond() - subtracted.toInstant(ZoneOffset.UTC).getEpochSecond();
        return new BigDecimal(second).divide(oneHours, 6, RoundingMode.HALF_UP);
    }

    /**
     * 返回秒级时间戳
     *
     * @param date 日期
     * @return 秒级时间戳
     */
    public static Long toSecondTimestamp(String date) {
        return LocalDateTime.parse(date, DateTimeFormatter.ofPattern(LOCAL_DATETIME_PATTERN)).atZone(ZONE_ID).toEpochSecond();
    }

    /**
     * 返回秒级时间戳
     *
     * @param date 日期
     * @return 秒级时间戳
     */
    public static Long toSecondTimestamp(LocalDateTime date) {
        return date.atZone(ZONE_ID).toEpochSecond();
    }

    /**
     * CST 特殊时间格式标识
     */
    private static final String DATE_CST = "CST";
    /**
     * 空格
     */
    private static final String EMPTY = " ";
    /**
     * 特殊格式的时间格式转换器
     */
    private static final DateTimeFormatter SSS_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S");
    private static final DateTimeFormatter NOT_EMPTY_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-ddHH:mm:ss");

    /**
     * 特定时间格式转换为普通时间格式
     * eg : 2024-05-21 11:01:42.0 CST
     * @param time
     * @return 时间字符串
     */
    public static String sssToDateStr(String time){
        try{
            if(time.contains(DATE_CST)){
                int endIndex = time.indexOf('.');
                if (endIndex != -1) {
                    // 如果找到了'.'，则截取到该位置之前
                    time = time.substring(0, endIndex);
                }
            }
        }catch (Exception e){
        }
        return time;
    }

    /**
     * 特定时间格式转换为普通时间格式
     * eg : 2024-05-2111:11:04
     * @param time
     * @return 时间字符串
     */
    public static String noEmptyToDateStr(String time){
        try{
            if(!time.contains(EMPTY)){
                time = time.substring(0, 10) + " " + time.substring(10);
            }
        }catch (Exception e){
        }
        return time;
    }

    /**
     * 物流轨迹转换时间
     *  2024-05-2111:11:04
     * 	2024-05-21 11:01:42.0 CST
     * 	2024-05-21 11:11:04
     * @param time
     * @return
     */
    public static LocalDateTime expressTrajectoryToLocalDateTime(String time){
        LocalDateTime localDateTime = LocalDateTime.now();
//        if(StringUtils.isBlank(time)){
//            return localDateTime;
//        }
        /**
         * 目前的格式是
         * 2024-05-2111:11:04
         * 2024-05-21 11:01:42.0 CST
         * 2024-05-21 11:11:04
         */
        if(time.contains(DATE_CST)){
            String timeStr = time.substring(0, time.lastIndexOf(" "));
            localDateTime = LocalDateTime.parse(timeStr, SSS_FORMATTER);
        }else if(!time.contains(EMPTY)){
            localDateTime = LocalDateTime.parse(time, NOT_EMPTY_FORMATTER);
        }else{
            localDateTime = TimeUtil.toLocalDateTime(time);
        }
        return localDateTime;
    }

    /**
     * 转换年月
     *
     * @param dateStr
     * @return
     */
    public static YearMonth toYearMonth(String dateStr) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");
        return YearMonth.parse(dateStr, formatter);
    }

    /**
     * 判断是否是过去年月
     * @param yearMonthStr 年月 yyyy-MM
     * @return
     */
    public static Boolean isPastMonth(String yearMonthStr){
        String[] split = yearMonthStr.split("-");
        String year = split[0];
        String month = split[1];
        System.out.println(Integer.parseInt(year)  + " : " + LocalDateTime.now().getYear());
        // 判断年份
        if (Integer.parseInt(year) < LocalDateTime.now().getYear()){
            return true;
        }
        System.out.println(Integer.parseInt(month)  + " : " + LocalDateTime.now().getMonthValue());
        // 判断月份
        if(Integer.parseInt(month) < LocalDateTime.now().getMonthValue()){
            return true;
        }
        return false;
    }
}
